/*----------------------------------------------------------------------------
Owner(s): Shane Whitfield
$Copyright: $
$Id: $
----------------------------------------------------------------------------*/

#include "world.h"
#include "go.h"
#include "gomgr.h"
#include "camera.h"
#include "render.h"
#include "engine.h"
#include "map.h"
#include "touchmgr.h"
#include "wave.h"

/*--------------------------------------------------------------------------*/

#define WORLD_BORDERS 0

/*--------------------------------------------------------------------------*/

void CWorld::CWorldBackground::SetWorldMat(const Vector2f& i_min, const Vector2f& i_max, EDepthLayer i_depthLayer)
{
	m_min = i_min;
	m_max = i_max;
	
	m_worldMat.SetPos(Vector2f::Zero);
	m_worldMat.SetDepth(g_gomgr.GetDepthFromDepthEnum(i_depthLayer));
}

void CWorld::CWorldBackground::Render()
{
	//Input assumption: Texture enable state is already set! Optimization
	
	Renderer::SetAlphaFunc(Renderer::EBarrier, 0.5);
	
	m_texture->Apply();
	m_worldMat.PushMatrix();
	BasicDrawObjects::DrawTexturedRect(m_min, m_max, Color4f(), Vector2f::Zero, Vector2f::One);
	m_worldMat.PopMatrix();
}

/*--------------------------------------------------------------------------*/

CWorld::CWorld(): super("CWorld")
{
	m_state = EState_Unloading;
	m_fileName[0] = 0;
	m_requestedFileName[0] = 0;
	m_isLoadRequested = false;
	m_level = NULL;
	m_wasLevelFailed = false;
	
	SetAbsMin(Vector2f(-5.5f, -5.5f));
	SetAbsMax(Vector2f(5.5f, 5.5f));
	SetMin(Vector2f(-5.0f, -5.0f));
	SetMax(Vector2f(5.0f, 5.0f));
}

void CWorld::initBackGround()
{
	m_worldBackgrounds[0].SetTexture(g_texturemgr.CreateTexture("bg_layer1.png"));
	m_worldBackgrounds[0].SetWorldMat(GetMin(), GetMax(), EDepthLayer_World1);
	m_worldBackgrounds[1].SetTexture(g_texturemgr.CreateTexture("bg_layer2.png"));
	m_worldBackgrounds[1].SetWorldMat(GetMin(), GetMax(), EDepthLayer_World2);
}

void CWorld::On_Command(const char* i_command, const char* i_parameters)
{
	if (!strcmp(i_command, "level_end"))
	{
		bool successed = atoi(i_parameters);
		if (successed)
		{
			setState(EState_LevelComplete);
		}
		else
		{
			setState(EState_LevelFailed);
		}
	}
	else if (!strcmp(i_command, "wave"))
	{
		CWave dbgWave(i_parameters, Vector2f::Zero);
		dbgWave.Spawn();
	}
}

void CWorld::OnInit()
{
	m_fileName[0] = 0;
	
	initBackGround();
			
	m_isLoadRequested = false;
}

void CWorld::Render()
{
	g_texturemgr.EnableTextures(true);
	
	for (int i = 0; i < DIM(m_worldBackgrounds); i++)
	{
		m_worldBackgrounds[i].Render();
	}
	
    g_texturemgr.EnableTextures(false);
	
	g_gomgr.Render();
	
	
#if DEBUG && WORLD_BORDERS
	//render the min/max box
	BasicDrawObjects::DrawSegment(m_min, Vector2f(m_min.x, m_max.y), Color3f(0.0f, 1.0f, 0.0f));
	BasicDrawObjects::DrawSegment(m_min, Vector2f(m_max.x, m_min.y), Color3f(0.0f, 1.0f, 0.0f));
	BasicDrawObjects::DrawSegment(m_max, Vector2f(m_min.x, m_max.y), Color3f(0.0f, 1.0f, 0.0f));
	BasicDrawObjects::DrawSegment(m_max, Vector2f(m_max.x, m_min.y), Color3f(0.0f, 1.0f, 0.0f));
	
	//render the min/max box
	BasicDrawObjects::DrawSegment(m_absMin, Vector2f(m_absMin.x, m_absMax.y), Color3f());
	BasicDrawObjects::DrawSegment(m_absMin, Vector2f(m_absMax.x, m_absMin.y), Color3f());
	BasicDrawObjects::DrawSegment(m_absMax, Vector2f(m_absMin.x, m_absMax.y), Color3f());
	BasicDrawObjects::DrawSegment(m_absMax, Vector2f(m_absMax.x, m_absMin.y), Color3f());
#endif
}

void CWorld::Update()
{
	for(;;)
	{
		EState prevState = m_state;
		switch(m_state)
		{
		case EState_Loading:
			{
				setState(EState_Loaded);
			}
			break;
		case EState_Loaded:
			{
				if (m_level)
				{
					m_level->Update();
					
					if (m_wasLevelFailed)
					{
						setState(EState_LevelFailed);
					}
					else if (m_level->IsComplete())
					{
						setState(EState_LevelComplete);
					}
				}
				
				g_gomgr.Update();
				
				//if (!g_gomgr.IsANodePlacing())
				{
					if (g_touchmgr.HasTouchEvent(ETouchType_SingleTouchStart))
					{	
						m_screenTouchPos = g_camera.ScreenToCameraSpace(g_touchmgr.GetTouchEventScreenPos(ETouchType_SingleTouchStart));
					}
					else if (g_touchmgr.HasTouchEvent(ETouchType_SingleTouchMoved))
					{	
						Vector2f prevWorldTouch = m_screenTouchPos;
						m_screenTouchPos = g_camera.ScreenToCameraSpace(g_touchmgr.GetTouchEventScreenPos(ETouchType_SingleTouchMoved));
					
						//move the camera by the change in touch points
						Vector2f moveVec = m_screenTouchPos - prevWorldTouch;
						g_camera.SetPos(g_camera.GetPos() - moveVec);
					}
				}
			}
			break;
		}
		
		if (m_state == prevState)
		{
			break;
		}
	}
}

void CWorld::setState(EState i_state)
{
	m_state = i_state;
	
	switch(m_state)
	{
	case EState_Loading:
		{
			if (m_requestedFileName[0] != '\0')
			{
				// construct the full world filename
				strcpy(m_fileName, m_requestedFileName);
				
				//create the level
				m_level = new CLevel(m_fileName);
				m_wasLevelFailed = false;
			}

			// request complete
			m_isLoadRequested = false;
			m_requestedFileName[0] = '\0';
		}
		break;
	case EState_LevelComplete:
		{
			//unlock the next world...
			g_mapmgr.UnlockNextLevel();
			
			//go back to the world map.
			g_mapmgr.RequestMap();
		}
		break;
	case EState_LevelFailed:
		{
			//go back to the world map. No Unlock!
			g_mapmgr.RequestMap();
		}
		break;
	case EState_Loaded:
		{
			m_level->Start();
		}
		break;
	case EState_Unloading:
		{
			m_fileName[0] = '\0';
			
			if (m_level)
			{
				delete m_level;
				m_level = NULL;
			}
		}
		break;
	}
}

void CWorld::LoadPendingWorld()
{
	setState(EState_Loading);
}

void CWorld::RequestLoad(const char* i_fileName)
{
	if (i_fileName[0] != '\0')
	{
		strcpy(m_requestedFileName, i_fileName);
		m_isLoadRequested = true;
	}
}

void CWorld::RequestReload()
{
	RequestLoad(m_fileName);
}

void CWorld::Unload()
{
	setState(EState_Unloading);
}

void CWorld::PostLoad()
{
	
}


/*-----------------------------------EOF!-----------------------------------*/ 